package com.xiyu.service.service.restaurant;

import com.xiyu.service.util.entity.EntityUtils;
import com.xiyu.service.enums.restaurant.plan.RestaurantPlanStatusEnum;
import com.xiyu.service.model.restaurant.plan.RestaurantPlanDraft;
import com.xiyu.service.repository.restaurant.plan.RestaurantPlanDetailRepository;
import com.xiyu.service.service.infra.data.DictNoService;
import com.xiyu.service.vo.restaurant.plan.PlanGetOutput;
import com.xiyu.service.model.restaurant.plan.RestaurantPlan;
import com.xiyu.service.repository.restaurant.plan.RestaurantPlanRepository;
import com.xiyu.service.vo.restaurant.plan.PlanUpdateStatusInput;
import com.xiyu.service.vo.restaurant.plan.PlanUpdateInput;
import com.xiyu.service.vo.restaurant.plan.PlanCreateInput;
import com.xiyu.service.vo.restaurant.plan.PlanQueryOutput;
import com.xiyu.service.vo.restaurant.plan.PlanQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.restaurant.PlanConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.restaurant.PlanErrorCode.*;

/**
 * 计划管理 Service 实现类
 */
@Service
@Validated
public class PlanServiceImpl implements PlanService {

    @Resource
    private RestaurantPlanRepository restaurantPlanRepository;

    @Resource
    private RestaurantPlanDetailRepository restaurantPlanDetailRepository;

    @Resource
    private DictNoService dictNoService;

    @Override
    public PageResult<PlanQueryOutput> query(PlanQueryInput inputVO) {
        Page<RestaurantPlan> planPage = restaurantPlanRepository.pageQuery(inputVO);
        List<PlanQueryOutput> planList = PlanConvert.INSTANCE.queryPageOutputConvert(planPage.getRows());
        return new PageResult<>(planList, planPage.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(PlanCreateInput inputVO) {
        // 校验已存在此时间的计划
        Optional<RestaurantPlan> optionalDuplicateTimePlan = restaurantPlanRepository.findDuplicateTimePlan(inputVO.getBeginTime(), inputVO.getEndTime());
        if(optionalDuplicateTimePlan.isPresent()){
            throw exception(PLAN_EXISTS_SAME_TIME);
        }
        Optional<RestaurantPlan> optionalDuplicateNamePlan = restaurantPlanRepository.findByPlanName(inputVO.getPlanName());
        if(optionalDuplicateNamePlan.isPresent()) {
            throw exception(PLAN_EXISTS_SAME_NAME);
        }
        RestaurantPlan newPlan = PlanConvert.INSTANCE.createInputConvert(inputVO);
        newPlan = RestaurantPlanDraft.$.produce(newPlan, draft -> {
            draft.setPlanStatus(RestaurantPlanStatusEnum.UNPUBLISHED.getValue())
                    .setPlanNo(dictNoService.produceNo("restaurantPlan"));
        });
        newPlan = restaurantPlanRepository.insert(newPlan);
        return newPlan.id();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(PlanUpdateInput inputVO) {
        Optional<RestaurantPlan> opDeletePlan = restaurantPlanRepository.findById(inputVO.getId());
        if(!opDeletePlan.isPresent()){
            throw exception(PLAN_NOT_EXISTS);
        }
        Optional<RestaurantPlan> optionalDuplicateTimePlan = restaurantPlanRepository.findDuplicateTimePlan(inputVO.getBeginTime(), inputVO.getEndTime());
        if(optionalDuplicateTimePlan.isPresent() && optionalDuplicateTimePlan.get().id() != inputVO.getId()){
            throw exception(PLAN_EXISTS_SAME_TIME);
        }
        Optional<RestaurantPlan> optionalDuplicateNamePlan = restaurantPlanRepository.findByPlanName(inputVO.getPlanName());
        if(optionalDuplicateNamePlan.isPresent() && optionalDuplicateNamePlan.get().id() != inputVO.getId()) {
            throw exception(PLAN_EXISTS_SAME_NAME);
        }
        RestaurantPlan updatePlan = PlanConvert.INSTANCE.updateInputConvert(inputVO);
        restaurantPlanRepository.save(updatePlan);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleted(Long id) {
        Optional<RestaurantPlan> opDeletePlan = restaurantPlanRepository.findById(id);
        if(!opDeletePlan.isPresent()){
            throw exception(PLAN_NOT_EXISTS);
        }
        restaurantPlanRepository.deleteById(id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(PlanUpdateStatusInput inputVO) {
        Optional<RestaurantPlan> opUpdatePlan = restaurantPlanRepository.findById(inputVO.getId());
        if(!opUpdatePlan.isPresent()){
            throw exception(PLAN_NOT_EXISTS);
        }
        if(opUpdatePlan.get().planStatus().equals(inputVO.getPlanStatus())){
            throw exception(PLAN_STATUS_DUP, (Objects.equals(inputVO.getPlanStatus(), RestaurantPlanStatusEnum.UNPUBLISHED.getValue()) ? "未发布" : "已发布"));
        }
        restaurantPlanRepository.updateStatus(inputVO.getId(), inputVO.getPlanStatus());
        return true;
    }

    @Override
    public PlanGetOutput get(Long id) {
        Optional<RestaurantPlan> opPlan = restaurantPlanRepository.getDetailById(id);
        if(!opPlan.isPresent()){
            throw exception(PLAN_NOT_EXISTS);
        }
        return PlanConvert.INSTANCE.getOutputConvert(opPlan.get());
    }

}
